// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See License.txt in the repository root.

package com.microsoft.tfs.core.clients.versioncontrol;

import java.util.ArrayList;
import java.util.List;

import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.Failure;
import com.microsoft.tfs.util.Check;

/**
 * Contains the status of a get operation that has completed.
 *
 * @since TEE-SDK-10.1
 * @threadsafety thread-compatible
 */
public final class GetStatus {
    private int numOperations;
    private int numConflicts;
    private int numUpdated;
    private int numWarnings;
    private int numResolvedConflicts;
    private final List<Failure> failures = new ArrayList<Failure>();
    private boolean haveResolvableWarnings;
    private boolean canceled = false;

    public GetStatus() {
    }

    /**
     * Combining the status from 2 Get calls.
     */
    public void combine(final GetStatus getStatus) {
        numOperations += getStatus.numOperations;
        numConflicts += getStatus.numConflicts;
        numUpdated += getStatus.numUpdated;
        numWarnings += getStatus.numWarnings;
        numResolvedConflicts += getStatus.numResolvedConflicts;
        haveResolvableWarnings |= getStatus.haveResolvableWarnings;
        failures.addAll(getStatus.failures);
    }

    /**
     * Get the failures generated by this invocation of get.
     */
    public Failure[] getFailures() {
        return failures.toArray(new Failure[failures.size()]);
    }

    /**
     * Adds a failure.
     *
     * @param failure
     *        the failure to add (must not be <code>null</code>)
     */
    public void addFailure(final Failure failure) {
        Check.notNull(failure, "failure"); //$NON-NLS-1$
        failures.add(failure);
    }

    /**
     * @return normally this is the number of failures returned by the server.
     *         If Get() is called with one or more items specified and they all
     *         fail to be valid local paths in the same workspace, this will be
     *         set to the number of items passed in (in that case, the server
     *         was never called).
     */
    public int getNumFailures() {
        return failures.size();
    }

    /**
     * @return the number of operations returned by the server. If the server
     *         returned no operations and no failures, everything was already up
     *         to date.
     */
    public int getNumOperations() {
        return numOperations;
    }

    public void setNumOperations(final int value) {
        numOperations = value;
    }

    public void decrementNumOperations() {
        numOperations--;
    }

    /**
     * @return The number of conflicts encountered by get.
     */
    public int getNumConflicts() {
        return numConflicts;
    }

    public void incrementNumConflicts() {
        numConflicts++;
    }

    public void setNumConflicts(final int value) {
        numConflicts = value;
    }

    /**
     * @return the number of operations which updated the workspace.
     */
    public int getNumUpdated() {
        return numUpdated;
    }

    public void incrementNumUpdated() {
        numUpdated++;
    }

    /**
     * @return the number of warnings encountered by get.
     */
    public int getNumWarnings() {
        return numWarnings;
    }

    public void incrementNumWarnings() {
        numWarnings++;
    }

    /**
     * @return the number of conflicts resolved (by auto resolve or manual
     *         resolve)
     */
    public int getNumResolvedConflicts() {
        return numResolvedConflicts;
    }

    public void setNumResolvedConflicts(final int numResolvedConflicts) {
        this.numResolvedConflicts = numResolvedConflicts;
    }

    public void incrementNumResolvedConflicts() {
        numResolvedConflicts++;
    }

    /**
     * When true, Get() had nothing to do (server returned no operations and no
     * failures).
     *
     * @return True when nothing needed to be done.
     */
    public boolean isNoActionNeeded() {
        return getNumOperations() == 0
            && getNumConflicts() == 0
            && getNumWarnings() == 0
            && getNumFailures() == 0
            && getNumResolvedConflicts() == 0;
    }

    public boolean haveResolvableWarnings() {
        return haveResolvableWarnings;
    }

    public void setHaveResolvableWarnings(final boolean value) {
        haveResolvableWarnings = value;
    }

    public boolean isCanceled() {
        return canceled;
    }

    public void setCanceled(final boolean canceled) {
        this.canceled = canceled;
    }

}
